;; functions for generating code for lemonphp rules

(defun lemonphp-gen-code-from-line (line)
  "LINE should be string;
example: \"nonterm0(A) ::= nonterm1(B) TERM1(C) nonterm2(D) . {}\""
  (let* ((result "")
         (nonterminal (substring (nth 0 (split-string line " ::= ")) 0 -3))
         (right-part  (nth 1 (split-string line " ::= ")))
         (elements (delete "" (split-string (substring right-part 0 -5) " "))))
;    (message "nonterminal: %s; elements: %S" nonterminal elements)
    (setq result (concat result (lemonphp-gen-node-numbers-code elements)))
    (setq result (concat result (lemonphp-gen-childs-code elements nonterminal)))
    (setq result (concat result (lemonphp-gen-position-code elements)))
    (setq result (concat result "    A = $result;"))
    result
    ))

(defun lemonphp-gen-position-code (elements)
  (let ((result ""))
    (if (> (length elements) 1)
        (let ((result "    $positions = array(")
              (num 0)
              (size (length elements)))
          (dolist (item elements)
            (let ((letter (substring item -2 -1)))
              (setq num (+ num 1))
              (setq result (concat result (format "%s->position()" letter)))
              (if (= num size)
                  (setq result (concat result ");
"))
                (setq result (concat result ", ")))))
          (setq result (concat result "    $result->set_position(block_formal_langs_node_position::summ($positions));
"))
          result)
      "    $result->set_position(B->position());
")))
      

(defun lemonphp-gen-childs-code (elements nonterminal)
  (let ((result (format "    $result = new block_formal_langs_ast_node_base(\"%s\", NULL, $this->node_num++, false);
" nonterminal)))
    (dolist (item elements)
      (setq result (concat result (format "    $result->add_child(%s);
" (substring item -2 -1)))))
    result))

(defun lemonphp-gen-node-numbers-code (elements)
  (let ((result ""))
    (dolist (item elements)
      (let ((itemname (substring item 0 -3))
            (letter (substring item -2 -1))
            (case-fold-search nil))
        (when (string-match "[A-Z]+" itemname)
          (setq result (concat result (format "    %s->set_number($this->node_num++);
" letter))))))
    result))

;; main interactive function for using in macro
(defun lemonphp-gen-code ()
  (interactive)
  (let ((result (lemonphp-gen-code-from-line (thing-at-point 'line))))
    (beginning-of-line)
    (search-forward ". {")
    (newline 2)
    (previous-line)
    (insert result)))
  

